package com.app.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;


public class AESTool {
	
	private static String ENCODING = "UTF-8";
	
	private static String SECRECY_TYPE = "AES";
	
	/**
	 * Android 和java平台通用的AES加密解密专用
	 */
	private static int SECRECY_NUMBER_128 = 128;
	
	/**
	 * java平台AES加密解密专用
	 */
	private static int SECRECY_NUMBER_256 = 256;
	
	private static String INIT_SECURERANDOM_STRING = "SHA1PRNG";
	
	/**
	 * ************************************************************************
	 * 根据Key获得128秘钥Android 平台的AES加密解密 <br><pre>
	 * 当前方法体key值必须为16位，否则会报错
	 * 方法getKeyAll的详细说明 <br>
	 * 编写者：N
	 * Email：swl@zcycjy.com
	 * 创建时间：2016-1-27 下午06:32:05 </pre>
	 * @return SecretKeySpec 秘钥
	 **************************************************************************
	 */
	private static SecretKeySpec getKeyAndroid(String keyWord){
		SecretKeySpec key = null;
		//当前方式Android 报错
		/*try {
			KeyGenerator kgen = KeyGenerator.getInstance(SECRECY_TYPE);
			SecureRandom secureRandom = SecureRandom.getInstance(INIT_SECURERANDOM_STRING);
			secureRandom.setSeed(keyWord.getBytes());
			kgen.init(SECRECY_NUMBER_128,secureRandom);
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			key = new SecretKeySpec(enCodeFormat,SECRECY_TYPE);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}*/
		key = new SecretKeySpec(keyWord.getBytes(),SECRECY_TYPE);
		return key;
	}
	
	/**
	 * ************************************************************************
	 * 根据Key获得256秘钥java平台的AES加密解密 <br><pre>
	 * 方法getKey的详细说明 <br>
	 * 编写者：wlsun
	 * Email：swl@zcycjy.com
	 * 创建时间：2016-1-28 14:19:43 </pre>
	 * @return SecretKeySpec 秘钥
	 **************************************************************************
	 */
	private static SecretKeySpec getKey(String keyWord){
		SecretKeySpec key = null;
		try {
			KeyGenerator kgen = KeyGenerator.getInstance(SECRECY_TYPE);
			SecureRandom secureRandom = SecureRandom.getInstance(INIT_SECURERANDOM_STRING);
			secureRandom.setSeed(keyWord.getBytes());
			kgen.init(SECRECY_NUMBER_256,secureRandom);
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			key = new SecretKeySpec(enCodeFormat,SECRECY_TYPE);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return key;
	}
	
	/**
	 * ************************************************************************
	 * Android 平台的AES加密 <br><pre>
	 * 方法dealAESEncryptAndroid的详细说明 <br>
	 * 编写者：wlsun
	 * Email：swl@zcycjy.com
	 * 创建时间：2016-1-27 下午06:20:31 </pre>
	 * @param content 内容
	 * @param keyWord 加密Key
	 * @return String 加密后的内容
	 **************************************************************************
	 */
	public static String dealAESEncryptAndroid(String content,String keyWord){
		try{
			SecretKeySpec key = getKeyByType(true, keyWord);
			Cipher cipher = Cipher.getInstance(SECRECY_TYPE);
			byte[] byteContent = content.getBytes(ENCODING);
			cipher.init(Cipher.ENCRYPT_MODE,key);
			byte[] result = cipher.doFinal(byteContent);
			return parseByte2HexStr(result);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * ************************************************************************
	 * 根据是否同时支持Android 和java平台标志获取Key<br><pre>
	 * 方法getKeyByType的详细说明 <br>
	 * 编写者：wlsun
	 * Email：swl@zcycjy.com
	 * 创建时间：2016-1-28 下午02:34:02 </pre>
	 * @return SecretKeySpec 说明
	 **************************************************************************
	 */
	private static SecretKeySpec getKeyByType(boolean isNotAllFlag, String keyWord) {
		SecretKeySpec key = null;
		if(isNotAllFlag) {
			key = getKeyAndroid(keyWord);
		} else {
			key = getKey(keyWord);
		}
		return key;
	}
	
	/**
	 * ************************************************************************
	 * java平台专用 AES加密 <br><pre>
	 * 方法dealAESEncrypt的详细说明 <br>
	 * 编写者：wlsun
	 * Email：swl@zcycjy.com
	 * 创建时间：2016-1-28 14:28:32 </pre>
	 * @param content 内容
	 * @param keyWord 加密Key
	 * @return String 加密后的内容
	 **************************************************************************
	 */
	public static String dealAESEncrypt(String content,String keyWord){
		try{
			SecretKeySpec key = getKeyByType(false, keyWord);
			Cipher cipher = Cipher.getInstance(SECRECY_TYPE);
			byte[] byteContent = content.getBytes();
			cipher.init(Cipher.ENCRYPT_MODE,key);
			byte[] result = cipher.doFinal(byteContent);
			return parseByte2HexStr(result);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * ************************************************************************
	 * Android 平台的AES解密 <br><pre>
	 * 方法dealAESDecryptAndroid的详细说明 <br>
	 * 编写者：wlsun
	 * Email：swl@zcycjy.com
	 * 创建时间：2016-1-27 下午06:20:31 </pre>
	 * @param content 内容
	 * @param keyWord 解密Key
	 * @return String 解密后的内容
	 **************************************************************************
	 */
	public static String dealAESDecryptAndroid(String content,String keyWord){
		try{
			byte[] contentByte = parseHexStr2Byte(content);
			SecretKeySpec key = getKeyByType(true, keyWord);
			Cipher cipher = Cipher.getInstance(SECRECY_TYPE);
			cipher.init(Cipher.DECRYPT_MODE,key);
			byte[] result = cipher.doFinal(contentByte);
			return new String(result, ENCODING);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * ************************************************************************
	 * java平台专用 AES解密 <br><pre>
	 * 方法dealAESDecrypt的详细说明 <br>
	 * 编写者：wlsun
	 * Email：swl@zcycjy.com
	 * 创建时间：2016-1-28 14:28:39 </pre>
	 * @param content 内容
	 * @param keyWord 解密Key
	 * @return String 解密后的内容
	 **************************************************************************
	 */
	public static String dealAESDecrypt(String content,String keyWord){
		try{
			byte[] contentByte = parseHexStr2Byte(content);
			SecretKeySpec key = getKeyByType(false, keyWord);
			Cipher cipher = Cipher.getInstance(SECRECY_TYPE);
			cipher.init(Cipher.DECRYPT_MODE,key);
			byte[] result = cipher.doFinal(contentByte);
			return new String(result);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 字符串转换***
	 * @param str 要进行隐藏的变量
	 * @param frontLen 前面需要保留几位
	 * @param endLen 后面需要保留几位
	 * @return
	 */
	public static String hidenNum(String str, int frontLen, int endLen) {
		if(str != null && str.length() > 10){
			int len = str.length() - frontLen - endLen;
			String xing = "";
			for (int i=0; i<len; i++) {
				xing += "*";
			}
			return str.substring(0, frontLen) + xing + str.substring(str.length() - endLen);
		}
		return str;
	}
	
	private static String parseByte2HexStr(byte[] buf){
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<buf.length;i++){
			String hex = Integer.toHexString(buf[i] & 0xFF);
			if(hex.length() == 1){
				hex = '0' + hex; 
			}
			sb.append(hex.toUpperCase());
		}
		return sb.toString();
	}
	
	private static byte[] parseHexStr2Byte(String hexStr){
		if(hexStr.length() < 1){
			return null;
		}
		byte[] result = new byte[hexStr.length()/2];
		for(int i=0;i<hexStr.length()/2;i++){
			int high = Integer.parseInt(hexStr.substring(i*2,i*2+1),16);
			int low = Integer.parseInt(hexStr.substring(i*2+1,i*2+2),16);
			result[i] = (byte)(high*16+low);
		}
		return result;
	}

	public static final String userID = "zcycjy"; // 正式环境广东地区机构账号
	public static final String userPwd = "2020zcpxg"; // 正式环境广东地区机构密码
	
	
	public static final String PUBLIC_URL = "https://kjw.shaanxi.gov.cn:7443/";
	
	public static final String APP_ID = "CZJJ@FJKJ1159"; // 应用系统凭证 
	
	public static final String APP_SECRET = "A34C8D82FEDE1B16E0532138A8C09C88"; // 凭证密钥

	public static void main(String[] args) throws Exception {
//		String s = dealAESDecrypt("19CE1806F1378BC6245E93D6B90F6812", "hwsc_pass");
		String s = dealAESEncrypt("hwsc_0801", "hwsc_pass");
		System.out.println(s);
	}
	
	/**
         * 构造Basic Auth认证头信息
	* 
	* @return
	*/
	public static String getHeader() {
		String auth = APP_ID + ":" + APP_SECRET;
		byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
		String authHeader = "Basic " + new String(encodedAuth);
		return authHeader;
	}
}
